package com.smcaiot.jfttask.north;

import com.smcaiot.core.exception.DomainException;
import com.smcaiot.jfttask.config.TestMybatisPlusConfig;
import com.smcaiot.jfttask.config.TestSpringConfig;
import com.smcaiot.jfttask.domain.*;
import com.smcaiot.jfttask.north.local.TaskAppService;
import com.smcaiot.jfttask.north.message.AddTaskRequest;
import com.smcaiot.jfttask.south.port.TaskFlowRepository;
import com.smcaiot.jfttask.south.port.TaskRepository;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.api.Assertions;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;

/**
 * @Author: cz
 * @Date: 2023/10/7
 * @Description:
 */
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringRunner.class)
//@PowerMockIgnore( {"javax.management.*", "javax.net.*"})
@PrepareForTest({TaskId.class, TaskBatchId.class, TaskFlowId.class, DomainException.class})
@ContextConfiguration(classes = {TestMybatisPlusConfig.class, TestSpringConfig.class})
@Slf4j
public class TaskAppServiceIT {
    @Autowired
    private TaskAppService taskAppService;
    @Autowired
    private TaskRepository taskRepository;
    @Autowired
    private TaskFlowRepository taskFlowRepository;
    private TaskId taskId = TaskId.from("34534-4353-ghfd-xexred3-34d");
    private TaskBatchId taskBatchId = TaskBatchId.from("4h46j-3j4h5-ghfd-xexred3-34d");
    private TaskFlowId taskFlowId = TaskFlowId.from("5h5h5-44j4j-ghfd-xexred3-34d");

    @Before
    public void setUp() throws Exception {
        PowerMockito.mockStatic(TaskId.class);
        PowerMockito.when(TaskId.next()).thenReturn(taskId);
        PowerMockito.when(TaskId.from(Mockito.anyString())).thenReturn(taskId);
        PowerMockito.mockStatic(TaskBatchId.class);
        PowerMockito.when(TaskBatchId.next()).thenReturn(taskBatchId);
        PowerMockito.when(TaskBatchId.from(Mockito.anyString())).thenReturn(taskBatchId);
        PowerMockito.mockStatic(TaskFlowId.class);
        PowerMockito.when(TaskFlowId.next()).thenReturn(taskFlowId);
        PowerMockito.when(TaskFlowId.from(Mockito.anyString())).thenReturn(taskFlowId);

        taskRepository.deleteByTaskId(taskId);
        taskFlowRepository.deleteByTaskFlowId(taskFlowId);
    }

    @Test
    public void should_add_task() {
        // given
        AddTaskRequest request = createAddTaskRequest();
        // when
        taskAppService.addTask(request);
        // then
        Task task = taskRepository.findByTaskId(taskId);
        Assertions.assertThat(task).isNotNull();
        Assertions.assertThat(task.getTaskId()).isEqualTo(taskId);
        Assertions.assertThat(task.getTaskName()).isNotBlank().isEqualTo(request.getTaskName());
        Assertions.assertThat(task.getType()).isNotBlank().isEqualTo(request.getType());
        //Assertions.assertThat(task.getTargetDepartment()).isNotBlank().isEqualTo(request.getTargetDepartment());
        Assertions.assertThat(task.getTaskCycle()).isNotNull();
        Assertions.assertThat(task.getTaskCycle().getCycleLength()).isNotNull();
        Assertions.assertThat(task.getTaskCycle().getCycleLength().getCode()).isEqualTo(request.getCycleLength());
        Assertions.assertThat(task.getTaskCycle().getCycleType()).isNotNull();
        Assertions.assertThat(task.getTaskCycle().getCycleType())
                .isEqualTo(new TaskCycle(request.getCycleLength()).getCycleType());

        TaskFlow taskFlow = taskFlowRepository.findByTaskFlowId(taskFlowId);
        Assertions.assertThat(taskFlow).isNotNull();
        Assertions.assertThat(taskFlow.getTaskFlowId()).isEqualTo(taskFlowId);
    }

    @Test
    public void should_rollback_when_add_task_exception() {
        String exceptionMsg = "新增任务测试事务";
        PowerMockito.mockStatic(DomainException.class);
        PowerMockito.when(DomainException.testTransaction(exceptionMsg)).thenThrow(new DomainException(exceptionMsg));
        // given
        AddTaskRequest request = createAddTaskRequest();
        // when
        Assertions.assertThatThrownBy(() -> taskAppService.addTask(request))
                .isInstanceOf(Exception.class)
                .hasMessageContaining(exceptionMsg);
        // then
        Task task = taskRepository.findByTaskId(taskId);
        Assertions.assertThat(task).isNull();
    }

    private AddTaskRequest createAddTaskRequest() {
        List<AddTaskRequest.AddTaskReceiver> taskReceivers = Mockito.anyList();
        taskReceivers.add(new AddTaskRequest.AddTaskReceiver().setTaskId(taskId.value()));
        AddTaskRequest request = new AddTaskRequest().setTaskId(taskId.value())
                .setTaskName("应用集成测试任务1")
                .setType("1")
                .setUserId("cesmz")
                .setTaskSettingReceiverList(taskReceivers)
                .setCcId(null)
                .setTargetDepartment("420185000000")
                .setCycleLength(7);
        return request;
    }
}
